#include "PreCompile.hpp"
#include "Module.hpp"
#include "../Shared/GObjHelpers.hpp"

extern "C"
{
  #include "ModuleGObject.h"
}

typedef GObject                     GObjectBase;
typedef BuildNGModule               GObjectCur;

typedef BuildNG::Object             CppBase;
typedef BuildNG::Module             CppCur;

typedef GObjectClass                GObjectBaseClass;
typedef BuildNGModuleClass          GObjectCurClass;

#define GOBJECT_CUR_TYPE            BUILDNG_TYPE_MODULE
#define GOBJECT_CUR_CLASS_CAST      BUILDNG_MODULE_CLASS
#define GOBJECT_BASE_CLASS_CAST     G_OBJECT_CLASS
#define GOBJECT_CUR_CAST            BUILDNG_MODULE

#define MAKE_FUNCTION_NAME(base_name) buildng_module_ ## base_name

static const gchar TYPE_NAME[] = "BuildNGModule";

#define IS_ABSTRACT

// the following code is generic:

namespace
{
#ifndef IS_ABSTRACT
  static void ctor(GType                  type,
                   guint                  n_construct_properties,
                   GObjectConstructParam *construct_properties)
  {
    GObjectCurClass *klass = GOBJECT_CUR_CLASS_CAST(g_type_class_peek(GOBJECT_CUR_TYPE));
    GObjectBaseClass *parent_class = GOBJECT_BASE_CLASS_CAST(g_type_class_peek_parent(klass));

    /* Invoke the parent constructor */  
    GObject *obj = parent_class->constructor(type,n_construct_properties,construct_properties);

    // TODO: fix C++ inheritence
    // TODO: handle parameters
    CppCur *cpp_class = new ((guint8*)obj + sizeof(GObjectCur)) CppCur();
  }
#endif

  static void class_init(gpointer class_ptr,gpointer class_data)
  {
    GObjectClass *gobj_class = G_OBJECT_CLASS(class_ptr);
#ifndef IS_ABSTRACT
    gobj_class->constructor = ctor;
#endif
  }
}

extern "C"
{
  GType MAKE_FUNCTION_NAME(get_type)()
  {
    static GType type = 0;
    if(type == 0)
    {
      static GTypeInfo info;
      info.class_size = sizeof(GObjectCurClass);

      info.base_init = NULL;
      info.base_finalize = NULL;

      info.class_init = class_init;
      info.class_finalize = NULL;
      info.class_data = NULL;

      info.instance_size = sizeof(GObjectClass) + sizeof(CppCur);
      info.n_preallocs = 0;
      info.instance_init = NULL;

      info.value_table = NULL;

      int flags = 0;
#ifdef IS_ABSTRACT
      flags |= G_TYPE_FLAG_ABSTRACT;
#endif
      type = g_type_register_static(G_TYPE_OBJECT,TYPE_NAME,&info,(GTypeFlags)flags);
    }

    return type;
  }
}

